package com.rowling.anno;

import com.google.auto.service.AutoService;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Set;

/**
 * 1.代码增强
 * 2.动态扩展
 * 实现方式：
 *  1.注解处理器
 *  2.反射
 *  代理模式：简单的设计模式，有一个目标类，还有一个代理类，我们客户端去调用目标类的时候，目标类
 *      干不了活，我们就使用代理类给它增强一下
 *  （
 *  静态代理:写业务，
 *  动态代理:Proxy：必须要有接口
 *           Cglib：可以不用接口
 *  ）
 */
@AutoService(Processor.class)   //使用google自动注册到META-INF
@SupportedAnnotationTypes("com.rowling.anno.FieldAnno")//需要解析的注解
@SupportedSourceVersion(SourceVersion.RELEASE_8)        //支持的jdk版本8
public class FieldAnnoProcessor extends AbstractProcessor {

    private StringBuilder sb = new StringBuilder();
    private int count ;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
    }

    /**
     * 只要实体类上增加了 @FieldAnno 就将实体类中属性保存到硬盘
     * @param annotations   表示需要解析哪些注解
     * @param roundEnv      每次的环境，根据环境可以得出元素
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //elementSet代表加了FiledAnno注解的所有元素（源码.java生成的语法树）
        Set<? extends Element> elementSet = roundEnv.getElementsAnnotatedWith(FieldAnno.class);


        //由于该注解处理器是处理 FieldAnno 注解的，而 FieldAnno 注解只添加在filed
        for (Element element :  elementSet) {
            VariableElement varField = (VariableElement) element;
            TypeElement enclosingElement = (TypeElement)varField.getEnclosingElement();//父元素是一个类
            String className = enclosingElement.getQualifiedName().toString();//类的名字
            Name fieldName = varField.getSimpleName();//属性名

            //拼接类和属性名
            sb.append("\n className = " + className ).append("\n fieldName = " + fieldName);

            //拼接属性上的注解
            FieldAnno anno = varField.getAnnotation(FieldAnno.class);
            sb.append("\n annoValue = " + anno.value()); //注解上的value值
            count++;
            sb.append("\n count = " + count);
        }
        generateFile(sb.toString());
        return false;
    }

    public void generateFile(String str){
        FileWriter fileWriter = null;
        try {
            File file = new File("D:\\nxjy\\anno\\testFile");
            if(!file.exists()){
                file.createNewFile();
            }
            fileWriter = new FileWriter(file);
            fileWriter.append(str);
            fileWriter.flush();
        }catch (Exception e){

        }finally {
            try {
                fileWriter.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }


    }


}
